package cn.ac.iie.di.ban.ycl.cleaner.handler;

import cn.ac.iie.di.ban.ycl.cleaner.common.Constants;
import cn.ac.iie.di.datadock.rdata.exchange.client.core.REFieldType;
import cn.ac.iie.di.datadock.rdata.exchange.client.v1.REMessage;
import org.ahocorasick.trie.Emit;
import org.ahocorasick.trie.Trie;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.lang.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @author 张明诚
 * @version V1.0
 * @date 2016-11-18 11:11:19
 * @desc
 */
public class ContentFilter implements FilterInterface {

    private final Logger LOG = LoggerFactory.getLogger(ContentFilter.class);
    private final List<Object> filterKeyWords;
    private final int filterContentSize;
    private List<Object[]> rubbishDatas;
    private String[] columnNames;
    private REFieldType[] types;
    private String docSchemaName;
    private Map<String, String> userDesc;
    private List<Object[]> datas;
    Trie trie;

    public ContentFilter(Configuration configuration) {
        this.filterKeyWords = configuration.getList(Constants.FILTER_CONTENT_KEYWORDS);//关键词列表
        this.filterContentSize = configuration.getInt(Constants.FILTER_CONTENT_SIZE);//内容长度
        trie = new Trie();
        for (Iterator<Object> it = filterKeyWords.iterator(); it.hasNext(); ) {
            String keyword = (String) it.next();
            String keywordUnicode = chToUnicode(keyword);
            trie.addKeyword(keywordUnicode);
        }
    }

    @Override
    public REMessage filter(REMessage message) throws Exception {
        columnNames = message.colNames;
        types = message.types;
        docSchemaName = message.docSchemaName;
        userDesc = message.userDesc;
        datas = message.data;
        rubbishDatas = new ArrayList<>();
        filter();
        return new REMessage(columnNames, types, datas, docSchemaName, userDesc);
    }

    /**
     * 过滤规则：推送消息无ID则为命中数据;
     * 包含图片数据的则为命中数据;
     * cont字段对应的文本内容长度如果小于等于filterContentSize，就与配置的关键词列表匹配， 命中则为有效数据；
     * 反之长度大于filterContentSize，则为命中数据；
     *
     * @throws java.lang.Exception
     */
    private void filter() throws Exception {
        List<Object[]> newMessage = new ArrayList<>();
        List<String> columnList = Arrays.asList(columnNames);

        int wxauIndex = columnList.indexOf("wx_au");
        if (wxauIndex < 0) {
            throw new Exception("wx_au field does not exists! " + ArrayUtils.toString(columnList));
        }
        int contIndex = columnList.indexOf("cont");
        if (contIndex < 0) {
            throw new Exception("cont field does not exists! " + ArrayUtils.toString(columnList));
        }
        int wxSfromIndex = columnList.indexOf("wx_sfrom");
        if (wxSfromIndex < 0) {
            throw new Exception("wx_sfrom field does not exists! " + ArrayUtils.toString(columnList));
        }

        //TODO 找金博士确定微信交互和群发的过滤规则
        try {
            for (Object[] data : this.datas) {

//##########################清洗老规则##############################
               /* //推送消息无ID
                String wxSfrom = (String) data[wxSfromIndex];
                if (wxSfrom == null || wxSfrom.isEmpty()) {
                    rubbishDatas.add(data);
                    LOG.debug("ID field is rubbish");
                    continue;
                }

                //包含图片
                String[] wxauContent = (String[]) data[wxauIndex];
                if (wxauContent.length == 1 && wxauContent[0].isEmpty()) {
                    rubbishDatas.add(data);
                    LOG.debug("wxauContent field is rubbish");
                    continue;
                }

                String content = (String) data[contIndex];
                if (content == null || content.isEmpty()) {
                    rubbishDatas.add(data);
                    LOG.debug("content field is rubbish");
                } else if (content.length() <= this.filterContentSize) {
                    LOG.debug("content field is parsing");
                    Collection<Emit> emits = trie.parseText(chToUnicode(content));
                    LOG.debug("content field parsed");
                    if (!emits.isEmpty() && emits.size() > 0) {
                        newMessage.add(data);
                        LOG.debug("not rubbish data");
                    } else {
                        rubbishDatas.add(data);
                        LOG.debug("content field is rubbish");
                    }
                } else {
                    newMessage.add(data);
                }
*/
//##########################只匹配消息ID和关键词##############################

                String wxSfrom = (String) data[wxSfromIndex];
                if (wxSfrom == null || wxSfrom.isEmpty()) {
                    rubbishDatas.add(data);
                    LOG.debug("ID field is rubbish");
                    continue;
                }

                String content = (String) data[contIndex];
                if (content == null || content.isEmpty()) {
                    rubbishDatas.add(data);//文字为空
                    LOG.debug("content field is rubbish");
                } else if (content.length() <= this.filterContentSize) {
                    LOG.debug("content field is parsing");
                    Collection<Emit> emits = trie.parseText(chToUnicode(content));
                    LOG.debug("content field parsed");
                    if (!emits.isEmpty() && emits.size() > 0) {//匹配到关键词
                        newMessage.add(data);
                        LOG.debug("not rubbish data");
                    } else {
                        rubbishDatas.add(data);
                        LOG.debug("content field is rubbish");
                    }
                } else {
                    newMessage.add(data);
                }

//##########################匹配图片和关键词##############################

               /* *//**
                 * 判断推送消息是否包含图片
                 *//*
                String[] wxauContent = (String[]) data[wxauIndex];
                *//**
                 * 没有图片则匹配关键词
                 *//*
                if (wxauContent.length == 1 && wxauContent[0].isEmpty()) {

                    String content = (String) data[contIndex];
                    if (content == null || content.isEmpty()) {
                        rubbishDatas.add(data);//文字为空
                        LOG.debug("content field is rubbish");
                    } else if (content.length() <= this.filterContentSize) {
                        LOG.debug("content field is parsing");
                        Collection<Emit> emits = trie.parseText(chToUnicode(content));
                        LOG.debug("content field parsed");
                        if (!emits.isEmpty() && emits.size() > 0) {//匹配到关键词
                            newMessage.add(data);
                            LOG.debug("not rubbish data");
                        } else {
                            rubbishDatas.add(data);
                            LOG.debug("content field is rubbish");
                        }
                    } else {
                        newMessage.add(data);
                    }
                }else {
                    *//**
                 * 有图片直接添加消息
                 *//*
                    newMessage.add(data);
                }*/
            }
        } catch (Exception e) {
            throw new Exception("filter error");
        }
        this.datas = newMessage;
    }

    private String chToUnicode(String content) {
        char[] utfBytes = content.toCharArray();
        String unicodeBytes = "";
        for (int byteIndex = 0; byteIndex < utfBytes.length; byteIndex++) {
            String hexB = Integer.toHexString(utfBytes[byteIndex]);
            if (hexB.length() <= 2) {
                hexB = "00" + hexB;
            }
            unicodeBytes = unicodeBytes + "\\u" + hexB;
        }
        return unicodeBytes;
    }

    public REMessage getRubbishMessage() {
        return new REMessage(columnNames, types, rubbishDatas, docSchemaName, userDesc);
    }

}
